// ----------------------------------------------------------------------------
// gfx_agl.m
// ----------------------------------------------------------------------------
// this code is from http://ysflight.in.coocan.jp/programming/fssimplewindow/j.html
#import <Cocoa/Cocoa.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include "../../base/fw_keycode.h"

#define NKEYBUF 256

struct FsMouseEventLog
{
    int eventType;
    int lb, mb, rb;
    int mx, my;
};

//----------------
// globals
static int exposure = 0;

static int keyIsDown[KEY_NUM_KEYCODE]={0};

static int nKeyBufUsed  = 0;
static int keyBuffer[NKEYBUF];

static int nCharBufUsed = 0;
static int charBuffer[NKEYBUF];

static int mouseLb = 0, mouseMb = 0, mouseRb = 0;
static int nMosBufUsed = 0;
static struct FsMouseEventLog mosBuffer[NKEYBUF];

static int FsNormalKeyCode[256]=
{
	0,                 // 0
	0,                 // 1
	0,                 // 2
	0,                 // 3
	0,                 // 4
	0,                 // 5
	0,                 // 6
	0,                 // 7
	0,                 // 8
	KEY_TAB,           // 9
	0,                 // 10
	0,                 // 11
	0,                 // 12
	KEY_ENTER,         // 13
	0,                 // 14
	0,                 // 15
	0,                 // 16
	0,                 // 17
	0,                 // 18
	0,                 // 19
	0,                 // 20
	0,                 // 21
	0,                 // 22
	0,                 // 23
	0,                 // 24
	0,                 // 25
	0,                 // 26
	KEY_ESC,           // 27
	0,                 // 28
	0,                 // 29
	0,                 // 30
	0,                 // 31
	KEY_SPACE,         // 32
	0,                 // 33
	0,                 // 34
	0,                 // 35
	0,                 // 36
	0,                 // 37
	0,                 // 38
	KEY_SINGLEQUOTE,   // 39
	0,                 // 40
	0,                 // 41
	0,                 // 42
	KEY_PLUS,          // 43
	KEY_COMMA,         // 44
	KEY_MINUS,         // 45
	KEY_DOT,           // 46
	KEY_SLASH,         // 47
	KEY_0,             // 48
	KEY_1,             // 49
	KEY_2,             // 50
	KEY_3,             // 51
	KEY_4,             // 52
	KEY_5,             // 53
	KEY_6,             // 54
	KEY_7,             // 55
	KEY_8,             // 56
	KEY_9,             // 57
	KEY_SEMICOLON,     // 58
	0,                 // 59
	0,                 // 60
	0,                 // 61
	0,                 // 62
	0,                 // 63
	0,                 // 64
	KEY_A,             // 65
	KEY_B,             // 66
	KEY_C,             // 67
	KEY_D,             // 68
	KEY_E,             // 69
	KEY_F,             // 70
	KEY_G,             // 71
	KEY_H,             // 72
	KEY_I,             // 73
	KEY_J,             // 74
	KEY_K,             // 75
	KEY_L,             // 76
	KEY_M,             // 77
	KEY_N,             // 78
	KEY_O,             // 79
	KEY_P,             // 80
	KEY_Q,             // 81
	KEY_R,             // 82
	KEY_S,             // 83
	KEY_T,             // 84
	KEY_U,             // 85
	KEY_V,             // 86
	KEY_W,             // 87
	KEY_X,             // 88
	KEY_Y,             // 89
	KEY_Z,             // 90
	KEY_LBRACKET,      // 91
	KEY_BACKSLASH,     // 92
	KEY_RBRACKET,      // 93
	0,                 // 94
	0,                 // 95
	0,                 // 96
	KEY_A,             // 97
	KEY_B,             // 98
	KEY_C,             // 99
	KEY_D,             // 100
	KEY_E,             // 101
	KEY_F,             // 102
	KEY_G,             // 103
	KEY_H,             // 104
	KEY_I,             // 105
	KEY_J,             // 106
	KEY_K,             // 107
	KEY_L,             // 108
	KEY_M,             // 109
	KEY_N,             // 110
	KEY_O,             // 111
	KEY_P,             // 112
	KEY_Q,             // 113
	KEY_R,             // 114
	KEY_S,             // 115
	KEY_T,             // 116
	KEY_U,             // 117
	KEY_V,             // 118
	KEY_W,             // 119
	KEY_X,             // 120
	KEY_Y,             // 121
	KEY_Z,             // 122
	KEY_LBRACKET,      // 123
	0,                 // 124
	KEY_RBRACKET,      // 125
	KEY_TILDA,         // 126
	KEY_BS,            // 127
	0,                 // 128
	0,                 // 129
	0,                 // 130
	0,                 // 131
	0,                 // 132
	0,                 // 133
	0,                 // 134
	0,                 // 135
	0,                 // 136
	0,                 // 137
	0,                 // 138
	0,                 // 139
	0,                 // 140
	0,                 // 141
	0,                 // 142
	0,                 // 143
	0,                 // 144
	0,                 // 145
	0,                 // 146
	0,                 // 147
	0,                 // 148
	0,                 // 149
	0,                 // 150
	0,                 // 151
	0,                 // 152
	0,                 // 153
	0,                 // 154
	0,                 // 155
	0,                 // 156
	0,                 // 157
	0,                 // 158
	0,                 // 159
	0,                 // 160
	0,                 // 161
	0,                 // 162
	0,                 // 163
	0,                 // 164
	0,                 // 165
	0,                 // 166
	0,                 // 167
	0,                 // 168
	0,                 // 169
	0,                 // 170
	0,                 // 171
	0,                 // 172
	0,                 // 173
	0,                 // 174
	0,                 // 175
	0,                 // 176
	0,                 // 177
	0,                 // 178
	0,                 // 179
	0,                 // 180
	0,                 // 181
	0,                 // 182
	0,                 // 183
	0,                 // 184
	0,                 // 185
	0,                 // 186
	0,                 // 187
	0,                 // 188
	0,                 // 189
	0,                 // 190
	0,                 // 191
	0,                 // 192
	0,                 // 193
	0,                 // 194
	0,                 // 195
	0,                 // 196
	0,                 // 197
	0,                 // 198
	0,                 // 199
	0,                 // 200
	0,                 // 201
	0,                 // 202
	0,                 // 203
	0,                 // 204
	0,                 // 205
	0,                 // 206
	0,                 // 207
	0,                 // 208
	0,                 // 209
	0,                 // 210
	0,                 // 211
	0,                 // 212
	0,                 // 213
	0,                 // 214
	0,                 // 215
	0,                 // 216
	0,                 // 217
	0,                 // 218
	0,                 // 219
	0,                 // 220
	0,                 // 221
	0,                 // 222
	0,                 // 223
	0,                 // 224
	0,                 // 225
	0,                 // 226
	0,                 // 227
	0,                 // 228
	0,                 // 229
	0,                 // 230
	0,                 // 231
	0,                 // 232
	0,                 // 233
	0,                 // 234
	0,                 // 235
	0,                 // 236
	0,                 // 237
	0,                 // 238
	0,                 // 239
	0,                 // 240
	0,                 // 241
	0,                 // 242
	0,                 // 243
	0,                 // 244
	0,                 // 245
	0,                 // 246
	0,                 // 247
	0,                 // 248
	0,                 // 249
	0,                 // 250
	0,                 // 251
	0,                 // 252
	0,                 // 253
	0,                 // 254
	0                  // 255
};

static int FsSpecialKeyCode[256]=
{
	KEY_UP,           // 0
	KEY_DOWN,         // 1
	KEY_LEFT,         // 2
	KEY_RIGHT,        // 3
	KEY_F1,           // 4
	KEY_F2,           // 5
	KEY_F3,           // 6
	KEY_F4,           // 7
	KEY_F5,           // 8
	KEY_F6,           // 9
	KEY_F7,           // 10
	KEY_F8,           // 11
	KEY_F9,           // 12
	KEY_F10,          // 13
	KEY_F11,          // 14
	KEY_F12,          // 15
	KEY_F1,           // 16 0x10
	KEY_F2,           // 17
	KEY_F3,           // 18
	KEY_F4,           // 19
	KEY_F5,           // 20
	KEY_F6,           // 21
	KEY_F7,           // 22
	KEY_F8,           // 23
	KEY_F9,           // 24
	KEY_F10,          // 25
	KEY_F11,          // 26
	KEY_F12,          // 27
	KEY_F1,           // 28
	KEY_F2,           // 29
	KEY_F3,           // 30
	KEY_F4,           // 31
	KEY_F5,           // 32 0x20
	KEY_F6,           // 33
	KEY_F7,           // 34
	KEY_F8,           // 35
	KEY_F9,           // 36
	KEY_F10,          // 37
	KEY_F11,          // 38
	KEY_INS,          // 39
	KEY_DEL,          // 40
	KEY_HOME,         // 41
	0,                // 42 Begin
	KEY_END,          // 43
	KEY_PAGEUP,       // 44
	KEY_PAGEDOWN,     // 45
	KEY_PRINTSCRN,    // 46
	KEY_SCROLLLOCK,   // 47
	KEY_PAUSEBREAK,   // 48 0x30
	0,                // 49
	KEY_PAUSEBREAK,   // 50
	0,                // 51 Reset
	0,                // 52 Stop
	0,                // 53 Menu
	0,                // 54 User
	0,                // 55 System
	KEY_PRINTSCRN,    // 56
	0,                // 57 Clear line
	0,                // 58 Clear display
	0,                // 59 Insert line
	0,                // 60 Delete line
	KEY_INS,          // 61
	KEY_DEL,          // 62
	KEY_PAGEUP,       // 63
	KEY_PAGEDOWN,     // 64
	0,                  // 65 Select
	0,                  // 66 Execute
	0,                  // 67 Undo
	0,                  // 68 Redo
	0,                  // 69 Find
	0,                  // 70 Help
	0,                  // 71 Mode Switch
	0,                  // 72
	0,                  // 73
	0,                  // 74
	0,                  // 75
	0,                  // 76
	0,                  // 77
	0,                  // 78
	0,                  // 79
	0,                  // 80
	0,                  // 81
	0,                  // 82
	0,                  // 83
	0,                  // 84
	0,                  // 85
	0,                  // 86
	0,                  // 87
	0,                  // 88
	0,                  // 89
	0,                  // 90
	0,                  // 91
	0,                  // 92
	0,                  // 93
	0,                  // 94
	0,                  // 95
	0,                  // 96
	0,                  // 97
	0,                  // 98
	0,                  // 99
	0,                  // 100
	0,                  // 101
	0,                  // 102
	0,                  // 103
	0,                  // 104
	0,                  // 105
	0,                  // 106
	0,                  // 107
	0,                  // 108
	0,                  // 109
	0,                  // 110
	0,                  // 111
	0,                  // 112
	0,                  // 113
	0,                  // 114
	0,                  // 115
	0,                  // 116
	0,                  // 117
	0,                  // 118
	0,                  // 119
	0,                  // 120
	0,                  // 121
	0,                  // 122
	0,                  // 123
	0,                  // 124
	0,                  // 125
	0,                  // 126
	0,                  // 127
	0,                  // 128
	0,                  // 129
	0,                  // 130
	0,                  // 131
	0,                  // 132
	0,                  // 133
	0,                  // 134
	0,                  // 135
	0,                  // 136
	0,                  // 137
	0,                  // 138
	0,                  // 139
	0,                  // 140
	0,                  // 141
	0,                  // 142
	0,                  // 143
	0,                  // 144
	0,                  // 145
	0,                  // 146
	0,                  // 147
	0,                  // 148
	0,                  // 149
	0,                  // 150
	0,                  // 151
	0,                  // 152
	0,                  // 153
	0,                  // 154
	0,                  // 155
	0,                  // 156
	0,                  // 157
	0,                  // 158
	0,                  // 159
	0,                  // 160
	0,                  // 161
	0,                  // 162
	0,                  // 163
	0,                  // 164
	0,                  // 165
	0,                  // 166
	0,                  // 167
	0,                  // 168
	0,                  // 169
	0,                  // 170
	0,                  // 171
	0,                  // 172
	0,                  // 173
	0,                  // 174
	0,                  // 175
	0,                  // 176
	0,                  // 177
	0,                  // 178
	0,                  // 179
	0,                  // 180
	0,                  // 181
	0,                  // 182
	0,                  // 183
	0,                  // 184
	0,                  // 185
	0,                  // 186
	0,                  // 187
	0,                  // 188
	0,                  // 189
	0,                  // 190
	0,                  // 191
	0,                  // 192
	0,                  // 193
	0,                  // 194
	0,                  // 195
	0,                  // 196
	0,                  // 197
	0,                  // 198
	0,                  // 199
	0,                  // 200
	0,                  // 201
	0,                  // 202
	0,                  // 203
	0,                  // 204
	0,                  // 205
	0,                  // 206
	0,                  // 207
	0,                  // 208
	0,                  // 209
	0,                  // 210
	0,                  // 211
	0,                  // 212
	0,                  // 213
	0,                  // 214
	0,                  // 215
	0,                  // 216
	0,                  // 217
	0,                  // 218
	0,                  // 219
	0,                  // 220
	0,                  // 221
	0,                  // 222
	0,                  // 223
	0,                  // 224
	0,                  // 225
	0,                  // 226
	0,                  // 227
	0,                  // 228
	0,                  // 229
	0,                  // 230
	0,                  // 231
	0,                  // 232
	0,                  // 233
	0,                  // 234
	0,                  // 235
	0,                  // 236
	0,                  // 237
	0,                  // 238
	0,                  // 239
	0,                  // 240
	0,                  // 241
	0,                  // 242
	0,                  // 243
	0,                  // 244
	0,                  // 245
	0,                  // 246
	0,                  // 247
	0,                  // 248
	0,                  // 249
	0,                  // 250
	0,                  // 251
	0,                  // 252
	0,                  // 253
	0,                  // 254
	0                   // 255
};

static int MacUnicodeToFsKeyCode(int uni)
{
	if(0<=uni && uni<256)
	{
		return FsNormalKeyCode[uni];
	}
	else if(0xf700<=uni && uni<0xf800)
	{
		return FsSpecialKeyCode[uni-0xf700];
	}
	return 0;
}

//----------------
// MacDelegate 
@interface MacDelegate : NSObject // NSApplicationDelegate
{
}
@end

@implementation MacDelegate
- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
{
    return YES;
}
@end

//----------------
// OpenGLWindow
@interface OpenGLWindow : NSWindow
{
}
@end

@implementation OpenGLWindow

- (id) initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
{
    [super initWithContentRect:contentRect styleMask:aStyle backing:bufferingType defer:flag];
    
    [[NSNotificationCenter defaultCenter]
     addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:self];
    
    [[NSNotificationCenter defaultCenter]
     addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:self];
    
    [self setAcceptsMouseMovedEvents:YES];
    
    printf("%s\n", __FUNCTION__);
    
    return self;
}

- (void) windowDidResize: (NSNotification *)notification
{
}

- (void) windowWillClose: (NSNotification *)notification
{
    [NSApp terminate:nil]; // This can also be exit(0); 
}
-(BOOL) acceptFirstResponder
{
    return YES;
}

- (BOOL)becomeFirstResponder
{
    return  YES;
}

- (BOOL)resignFirstResponder
{
    return YES;
}

@end

@interface OpenGLView : NSOpenGLView
{
}
- (void) drawRect:(NSRect)dirtyRect;
@end

@implementation OpenGLView

-(void) drawRect:(NSRect)dirtyRect
{
    printf("%s\n", __FUNCTION__);
    exposure = 1;
}

-(void) prepareOpenGL
{
    printf("%s\n", __FUNCTION__);
}

//-(NSMenu *)menuForEvent:(NSEvent *)event
//{
//    printf("%s\n", __FUNCTION__);
//    return [NSView defaultMenu];
//}

-(void) flagsChanged:(NSEvent *)theEvent
{
    NSUInteger flags;
    flags = [theEvent modifierFlags];
    
    if (flags & NSAlphaShiftKeyMask) // Caps 
    {
        if (keyIsDown[KEY_CAPSLOCK]==0 && nKeyBufUsed<NKEYBUF)
        {
            keyBuffer[nKeyBufUsed++] = KEY_CAPSLOCK;
        }
        keyIsDown[KEY_CAPSLOCK] = 1;
    }
    else
    {
        keyIsDown[KEY_CAPSLOCK] = 0;
    }
    
    if (flags & NSShiftKeyMask)
    {
        if (keyIsDown[KEY_SHIFT]==0 && nKeyBufUsed<NKEYBUF)
        {
            keyBuffer[nKeyBufUsed++] = KEY_SHIFT;
        }
        keyIsDown[KEY_SHIFT] = 1;
    }
    else
    {
        keyIsDown[KEY_SHIFT] = 0;
    }

    if (flags & NSControlKeyMask)
    {
        if (keyIsDown[KEY_CTRL]==0 && nKeyBufUsed<NKEYBUF)
        {
            keyBuffer[nKeyBufUsed++] = KEY_CTRL;
        }
        keyIsDown[KEY_CTRL] = 1;
    }
    else
    {
        keyIsDown[KEY_CTRL] = 0;
    }

    if ((flags & NSAlternateKeyMask) || (flags & NSCommandKeyMask))
    {
        if (keyIsDown[KEY_ALT]==0 && nKeyBufUsed<NKEYBUF)
        {
            keyBuffer[nKeyBufUsed++] = KEY_ALT;
        }
        keyIsDown[KEY_ALT] = 1;
    }
    else
    {
        keyIsDown[KEY_ALT] = 0;
    }
}

-(void) keyDown:(NSEvent *)theEvent
{
    NSUInteger flags;
	flags=[theEvent modifierFlags];
    
    NSString *chrs, *chrsNoMod;
    chrs = [theEvent characters];
    
    if (0==(flags & NSCommandKeyMask) && [chrs length]>0)
    {
        int unicode;
        unicode = [chrs characterAtIndex:0];
        
        if (32<=unicode && unicode<128 && nCharBufUsed<NKEYBUF)
        {
            charBuffer[nCharBufUsed++] = unicode;
        }
    }
    
    chrsNoMod = [theEvent charactersIgnoringModifiers];
    if ([chrsNoMod length]>0)
    {
        int unicode, fsKey;
        unicode = [chrsNoMod characterAtIndex:0];
        fsKey = MacUnicodeToFsKeyCode(unicode);
        
        if (fsKey!=0)
        {
            keyIsDown[fsKey] = 1;
            if (nKeyBufUsed<NKEYBUF)
            {
                keyBuffer[nKeyBufUsed++] = fsKey;
            }
        }
    }
}

-(void) keyUp:(NSEvent *)theEvent
{
    NSString *chrs, *chrsNoMod;
    chrs = [theEvent characters];
    
    if ([chrs length]>0)
    {
        int unicode;
        unicode = [chrs characterAtIndex:0];
    }
    
    chrsNoMod = [theEvent charactersIgnoringModifiers];
    if ([chrsNoMod length]>0)
    {
        int unicode, fsKey;
        unicode = [chrsNoMod characterAtIndex:0];
        fsKey = MacUnicodeToFsKeyCode(unicode);
        
        if (fsKey != 0)
        {
            keyIsDown[fsKey] = 0;
        }
    }
}

-(void) mouseMoved:(NSEvent *)theEvent
{
    if (0<nMosBufUsed && FSMOUSEEVENT_MOVE==mosBuffer[nMosBufUsed-1].eventType)
    {
        NSRect rect;
        rect = [self frame];
        
        mosBuffer[nMosBufUsed-1].mx = (int)[theEvent locationInWindow].x;
        mosBuffer[nMosBufUsed-1].my = rect.size.height - 1 - (int)[theEvent locationInWindow].y;
    }
    else if(NKEYBUF>nMosBufUsed)
    {
        NSRect rect;
        rect = [self frame];
        
        mosBuffer[nMosBufUsed].eventType = FSMOUSEEVENT_MOVE;
        mosBuffer[nMosBufUsed].mx = (int)[theEvent locationInWindow].x;
        mosBuffer[nMosBufUsed].my = (int)rect.size.height - 1 - (int)[theEvent locationInWindow].y;
        mosBuffer[nMosBufUsed].lb = mouseLb;
        mosBuffer[nMosBufUsed].mb = mouseMb;
        mosBuffer[nMosBufUsed].rb = mouseRb;
        nMosBufUsed++;
    }
}

#if 0
-(void) mouseDragged:(NSEvent *)theEvent
{
    [self mouseDragged:theEvent];
}

- (void) rightMouseDragged:(NSEvent *)theEvent
{
    [self mouseMoved:theEvent];
}

- (void) otherMouseDragged:(NSEvent *)theEvent
{
    [self mouseMoved:theEvent];
}
#endif
- (void) mouseDown:(NSEvent *)theEvent
{
    mouseLb = 1;
    if(NKEYBUF>nMosBufUsed)
    {
        NSRect rect;
        rect = [self frame];
        
        mosBuffer[nMosBufUsed].eventType = FSMOUSEEVENT_LBUTTONDOWN;
        mosBuffer[nMosBufUsed].mx = (int)[theEvent locationInWindow].x;
        mosBuffer[nMosBufUsed].my = (int)rect.size.height - 1 - (int)[theEvent locationInWindow].y;
        mosBuffer[nMosBufUsed].lb = mouseLb;
        mosBuffer[nMosBufUsed].mb = mouseMb;
        mosBuffer[nMosBufUsed].rb = mouseRb;
        nMosBufUsed++;
    }
}

- (void) mouseUp:(NSEvent *)theEvent
{
    mouseLb = 0;
    if(NKEYBUF>nMosBufUsed)
    {
        NSRect rect;
        rect = [self frame];
        
        mosBuffer[nMosBufUsed].eventType = FSMOUSEEVENT_LBUTTONUP;
        mosBuffer[nMosBufUsed].mx = (int)[theEvent locationInWindow].x;
        mosBuffer[nMosBufUsed].my = (int)rect.size.height - 1 - (int)[theEvent locationInWindow].y;
        mosBuffer[nMosBufUsed].lb = mouseLb;
        mosBuffer[nMosBufUsed].mb = mouseMb;
        mosBuffer[nMosBufUsed].rb = mouseRb;
        nMosBufUsed++;
    }
}

- (void) rightMouseDown:(NSEvent *)theEvent
{
    mouseRb = 1;
    if(NKEYBUF>nMosBufUsed)
    {
        NSRect rect;
        rect = [self frame];
        
        mosBuffer[nMosBufUsed].eventType = FSMOUSEEVENT_RBUTTONDOWN;
        mosBuffer[nMosBufUsed].mx = (int)[theEvent locationInWindow].x;
        mosBuffer[nMosBufUsed].my = (int)rect.size.height - 1 - (int)[theEvent locationInWindow].y;
        mosBuffer[nMosBufUsed].lb = mouseLb;
        mosBuffer[nMosBufUsed].mb = mouseMb;
        mosBuffer[nMosBufUsed].rb = mouseRb;
        nMosBufUsed++;
    }
}

- (void) rightMouseUp:(NSEvent *)theEvent
{
    mouseRb = 0;
    if(NKEYBUF>nMosBufUsed)
    {
        NSRect rect;
        rect = [self frame];
        
        mosBuffer[nMosBufUsed].eventType = FSMOUSEEVENT_RBUTTONUP;
        mosBuffer[nMosBufUsed].mx = (int)[theEvent locationInWindow].x;
        mosBuffer[nMosBufUsed].my = (int)rect.size.height - 1 - (int)[theEvent locationInWindow].y;
        mosBuffer[nMosBufUsed].lb = mouseLb;
        mosBuffer[nMosBufUsed].mb = mouseMb;
        mosBuffer[nMosBufUsed].rb = mouseRb;
        nMosBufUsed++;
    }
}

- (void) otherMouseDown:(NSEvent *)theEvent
{
    mouseMb = 1;
    if(NKEYBUF>nMosBufUsed)
    {
        NSRect rect;
        rect = [self frame];
        
        mosBuffer[nMosBufUsed].eventType = FSMOUSEEVENT_MBUTTONDOWN;
        mosBuffer[nMosBufUsed].mx = (int)[theEvent locationInWindow].x;
        mosBuffer[nMosBufUsed].my = (int)rect.size.height - 1 - (int)[theEvent locationInWindow].y;
        mosBuffer[nMosBufUsed].lb = mouseLb;
        mosBuffer[nMosBufUsed].mb = mouseMb;
        mosBuffer[nMosBufUsed].rb = mouseRb;
        nMosBufUsed++;
    }
}

- (void) otherMouseUp:(NSEvent *)theEvent
{
    mouseMb = 0;
    if(NKEYBUF>nMosBufUsed)
    {
        NSRect rect;
        rect = [self frame];
        
        mosBuffer[nMosBufUsed].eventType = FSMOUSEEVENT_MBUTTONUP;
        mosBuffer[nMosBufUsed].mx = (int)[theEvent locationInWindow].x;
        mosBuffer[nMosBufUsed].my = (int)rect.size.height - 1 - (int)[theEvent locationInWindow].y;
        mosBuffer[nMosBufUsed].lb = mouseLb;
        mosBuffer[nMosBufUsed].mb = mouseMb;
        mosBuffer[nMosBufUsed].rb = mouseRb;
        nMosBufUsed++;
    }
}

@end

//----------------
// External interface 

static void setApplicationMenu(void)
{
    /* warning: this code is very odd */
    NSMenu *appleMenu;
    NSMenuItem *menuItem;
    NSString *title;
    NSString *appName;
    
    appName = @"OpenGL App";
    appleMenu = [[NSMenu alloc] initWithTitle:@""];

    /* Add menu items */
    title = [@"About " stringByAppendingString:appName];
    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
    
    [appleMenu addItem:[NSMenuItem separatorItem]];
    
    title = [@"Hide " stringByAppendingString:appName];
    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
    
    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
    
    [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
    
    [appleMenu addItem:[NSMenuItem separatorItem]];
    
    title = [@"Quit " stringByAppendingString:appName];
    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
    
    /* Put menu into the menubar */
    menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
    [menuItem setSubmenu:appleMenu];
    [[NSApp mainMenu] addItem:menuItem];
    
    /* Tell the application object that this is now the application menu */
    //[NSApp setAppleMenu:appleMenu];
    [NSApp performSelector:@selector(setAppleMenu:) withObject:appleMenu];
    /* Finally give up our references to the objects */

    [appleMenu release];
    [menuItem release];
}

/* Create a window menu */
static void setupWindowMenu(void)
{
    NSMenu      *windowMenu;
    NSMenuItem  *windowMenuItem;
    NSMenuItem  *menuItem;
    
    windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
    
    /* "Minimize" item */
    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
    [windowMenu addItem:menuItem];
    [menuItem release];
    
    /* Put menu into the menubar */
    windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
    [windowMenuItem setSubmenu:windowMenu];
    [[NSApp mainMenu] addItem:windowMenuItem];
    
    /* Tell the application object that this is now the window menu */
    [NSApp setWindowsMenu:windowMenu];
    
    /* Finally give up our references to the objects */
    [windowMenu release];
    [windowMenuItem release];
}

void GfxAddMenu(void)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    NSMenu *mainMenu = [NSMenu alloc];
    [mainMenu initWithTitle:@"Minimum"];
    
    NSMenuItem *fileMenu;
    fileMenu = [[NSMenuItem alloc] initWithTitle:@"File" action:NULL keyEquivalent:[NSString string]];
    [mainMenu addItem:fileMenu];
    
    NSMenu *fileSubMenu;
    fileSubMenu = [[NSMenu alloc] initWithTitle:@"File"];
    [fileMenu setSubmenu:fileSubMenu];
    
    NSMenuItem *fileMenu_Quit;
    fileMenu_Quit = [[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
    [fileMenu_Quit setTarget:NSApp];
    [fileSubMenu addItem:fileMenu_Quit];
    
    [NSApp setMainMenu:mainMenu];
    
    [pool release];
}

void GfxApplicationPath(void)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    char cwd[256];
    getcwd(cwd,255);
    printf("cwd(Initial): %s\n", cwd);
    
    NSString *path;
    path = [[NSBundle mainBundle] bundlePath];
    printf("BundlePath:%s\n",[path UTF8String]);

    [[NSFileManager defaultManager] changeCurrentDirectoryPath:path];
    
    getcwd(cwd, 255);
    printf("cwd(Changed): %s\n", cwd);
    
    [pool release];
}

OpenGLWindow *openGLWnd=nil;
OpenGLView *openGLView=nil;

void GfxOpenWindowC( int x0, int y0, int width, int height)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    [NSApplication sharedApplication];
    [NSBundle loadNibNamed:@"MainMenu" owner:NSApp];
    
    ProcessSerialNumber psn = { 0, kCurrentProcess };
    TransformProcessType(&psn, kProcessTransformToForegroundApplication);
    SetFrontProcess(&psn);
    
    MacDelegate *delegate;
    delegate = [MacDelegate alloc];
    [delegate init];
    [NSApp setDelegate:delegate];
    
  //  [NSApp finishLaunching];
    
    NSRect contRect;
    contRect = NSMakeRect(x0, y0, width, height);
    
    unsigned int windowStyle = 
        NSTitledWindowMask | 
        NSClosableWindowMask | 
        NSMiniaturizableWindowMask | 
        NSResizableWindowMask;
    
    openGLWnd = [OpenGLWindow alloc];
    [openGLWnd
        initWithContentRect:contRect
        styleMask:windowStyle
        backing:NSBackingStoreBuffered
        defer:NO];
    
    NSOpenGLPixelFormat *format;
    NSOpenGLPixelFormatAttribute formatAttrib[] =
    {
        NSOpenGLPFAWindow,
        NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)32,
        NSOpenGLPFADoubleBuffer,
        0
    };
    
    format = [NSOpenGLPixelFormat alloc];
    [format initWithAttributes: formatAttrib];

    openGLView = [OpenGLView alloc];
    contRect = NSMakeRect(0, 0, width, height);
    [openGLView initWithFrame:contRect pixelFormat:format];
    
    [openGLWnd setContentView:openGLView];
    [openGLWnd makeFirstResponder:openGLView];
    
    [openGLWnd makeKeyAndOrderFront:nil];
    [openGLWnd makeMainWindow];
    
    [NSApp activateIgnoringOtherApps:YES];
    
  //  GfxAddMenu();
    [NSApp setMainMenu:[[NSMenu alloc] init]];
    setApplicationMenu();
    setupWindowMenu();
	{
	#if 0
		CGLContextObj ctx; 
		CGLPixelFormatObj pix; 
		GLint npix; 
		/* 
		 CGLPixelFormatAttribute attribs[] = { 
		 kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core, 
		 0 
		 }; 
		 */ 
		int attribs[] = { 
			(int)kCGLPFAOpenGLProfile,  (int)kCGLOGLPVersion_3_2_Core, 0 
		}; 
		CGLChoosePixelFormat((CGLPixelFormatAttribute *)attribs, &pix, &npix); 
		CGLCreateContext(pix, NULL, &ctx); 
		CGLSetCurrentContext(ctx); 
	#endif	
		printf("%s %s\n", glGetString(GL_RENDERER), glGetString(GL_VERSION));
	}
    
    [NSApp finishLaunching];
    
    [pool release];
    
    for( int i=0; i<KEY_NUM_KEYCODE; ++i )
    {
        keyIsDown[i] = 0;
    }
    
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClearDepth(1.0f);
    glDisable(GL_DEPTH_TEST);
    
    glViewport(0, 0, width, height);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, (float)width-1, (float)height-1, 0, -1, 1);
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    glShadeModel(GL_FLAT);
    glPointSize(1);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glColor3ub(0, 0, 0);
    
}

void GfxGetWindowSizeC(int *width, int* height)
{
    NSRect rect;
    rect = [openGLView frame];
    *width = rect.size.width;
    *height = rect.size.height;
}

void GfxPollDeviceC(void)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    while(1)
    {
        [pool release];
        pool = [[NSAutoreleasePool alloc] init];
        
        NSEvent *event;
        event = [NSApp
                 nextEventMatchingMask: NSAnyEventMask
                 untilDate: [NSDate distantPast]
                 inMode: NSDefaultRunLoopMode
                 dequeue: YES];
        if([event type] == NSRightMouseDown)
        {
            printf("R mouse down event.\n");
        }
        if( event != nil )
        {
            [NSApp sendEvent:event];
            [NSApp updateWindows];
        }
        else
        {
            break;
        }
    }
    [pool release];
}

void GfxSleepC(int ms)
{
    if(ms>0)
    {
        double sec;
        sec = (double)ms / 1000.0;
        [NSThread sleepForTimeInterval:sec];
    }
}

int GfxPassedTimeC(void)
{
    int ms;
    
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    static NSTimeInterval last = 0.0;
    NSTimeInterval now;
    
    now = [[NSDate date] timeIntervalSince1970];
    
    NSTimeInterval passed;
    passed = now - last;
    ms = (int)(1000.0 * passed);
    
    if(ms<0)
    {
        ms = 1;
    }
    last = now;
    
    [pool release];
    
    return ms;
}

void GfxMouseC(int *lb, int *mb, int *rb, int *mx, int *my)
{
    *lb = mouseLb;
    *mb = mouseMb;
    *rb = mouseRb;
    
    NSPoint loc;
    loc = [NSEvent mouseLocation];
    loc = [openGLWnd convertScreenToBase:loc];
    loc = [openGLView convertPointFromBase:loc];
    
    NSRect rect;
    rect = [openGLView frame];
    *mx = loc.x;
    *my = rect.size.height - 1 - loc.y;
}

int GfxMouseEventC(int *lb,int *mb,int *rb,int *mx,int *my)
{
    if(0<nMosBufUsed)
    {
        const int eventType = mosBuffer[0].eventType;
        *lb = mosBuffer[0].lb;
        *mb = mosBuffer[0].mb;
        *rb = mosBuffer[0].rb;
        *mx = mosBuffer[0].mx;
        *my = mosBuffer[0].my;
        
        int i;
        for(i=0; i<nMosBufUsed-1; i++)
        {
            mosBuffer[i] = mosBuffer[i+1];
        }
        nMosBufUsed--;
        return eventType;
    }
    GfxMouseC(lb, mb, rb, mx, my);
    return FSMOUSEEVENT_NONE;
}

void GfxSwapBufferC(void)
{
    [[openGLView openGLContext] flushBuffer];
}

int GfxInKeyC(void)
{
    if(0<nKeyBufUsed)
    {
        int i, gfxkey;
        gfxkey = keyBuffer[0];
        nKeyBufUsed--;
        for(i=0; i<nKeyBufUsed; i++)
        {
            keyBuffer[i] = keyBuffer[i+1];
        }
        return gfxkey;
    }
    return 0;
}

int GfxInKeyCharC(void)
{
    if(0<nCharBufUsed)
    {
        int i, c;
        c = charBuffer[0];
        nCharBufUsed--;
        for(i=0; i<nCharBufUsed;  i++)
        {
            charBuffer[i] = charBuffer[i+1];
        }
        return c;
    }
    return 0;
}

int GfxKeyStateC(int keyState)
{
    if(0<=keyState && keyState < KEY_NUM_KEYCODE)
    {
        return keyIsDown[keyState];
    }
    return 0;
}

void GfxChangeToProgramDirC(void)
{
    NSString *path;
	path=[[NSBundle mainBundle] bundlePath];
	printf("BundlePath:%s\n",[path UTF8String]);
    
	[[NSFileManager defaultManager] changeCurrentDirectoryPath:path];
}

int GfxCheckExposureC(void)
{
	int ret;
	ret=exposure;
	exposure=0;
	return ret;
}
